#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sqlite3.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

#define NAME_SIZE 64
#define PASSWORD_SIZE 64
#define SEARCH 64
#define NO -1
#define MEMBER_LISTNAME "member"
#define DICTIONALY_LISTNAME "dic"




typedef struct member{
    char name[NAME_SIZE];
    char password[PASSWORD_SIZE];
}membernode,*memberlist;

/*
    指针检查
*/
int pointer_check(int num,void* value1,void* value2,void* value3,void* value4,void* value5,void* value6){
    if(num >=1){
        if(value1 == NULL){
            return -1;
        }
    }
    if(num >=2){
        if(value2 == NULL){
            return -1;
        }
    }
    if(num >=3){
        if(value3 == NULL){
            return -1;
        }
    }
    if(num >=4){
        if(value4 == NULL){
            return -1;
        }
    }
    if(num >=5){
        if(value5 == NULL){
            return -1;
        }
    }
    if(num >=6){
        if(value6 == NULL){
            return -1;
        }
    }
    return 0;
}

/*
    传入字符串指针time_str，将当前时间写入进time_str
*/
int now_time(char* time_str){
    if(pointer_check(1,time_str,NULL,NULL,NULL,NULL,NULL) == -1 ){
        printf("pointer_chek err\n");
        return -1;
    }

    time_t timep;
    struct tm *p;


    time(&timep); // 获取当前时间的秒数
    p = gmtime(&timep); // 将秒数转换为 tm 结构体

    // 将时间信息格式化为字符串
    sprintf(time_str, "%d年%d月%d日 %d:%d:%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);
    // printf("当前时间为：%s\n",time_str);


    return 0;
}

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
    if(pointer_check(2,argv,azColName,NULL,NULL,NULL,NULL) == -1 ){
        printf("pointer_chek err\n");
        return -1;
    }
    int i=0;
    if(NotUsed != NULL){
        *((int*)NotUsed)=argc;
    }
    // printf("argc =%d\n",argc);
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

/*
    listname:要插入的目标表名  value1:第一栏的值   value2:第二栏的值 
    将值插入表中
*/
int do_insert(sqlite3 *db,char* listname,char* value1,char* value2) {
    if(pointer_check(4,listname,value1,value2,db,NULL,NULL) == -1 ){
        printf("pointer_chek err\n");
        return -1;
    }
    const char ch[128]="";
    sprintf((char *)ch,"insert into %s values('%s','%s')",listname,value1,value2);

    char *zErrMsg = NULL;
    
    if (sqlite3_exec(db, ch, NULL,NULL, &zErrMsg) != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return -1;
    }
    return 0;
}

/**
 * * @brief 删除记录 
 * * @param db 
 * */ 
// void do_delete(sqlite3 *db) {
//     if(db == NULL){
//         return -1;
//     }
//     char name[64]="";
//     const char ch[128]="";
//     printf("请输入姓名:\n");
//     scanf("%s",name);
//     sprintf((char *)ch,"delete from tbl1 where name='%s'",name);
//     printf("%s\n",ch);
//     char *zErrMsg = NULL; 
//     if (sqlite3_exec(db, ch, NULL,NULL, &zErrMsg) != SQLITE_OK)
//     {
//         fprintf(stderr, "SQL error: %s\n", zErrMsg);
//         sqlite3_free(zErrMsg);
//     }
//     return;
// }


/*  
    do_search
    listname:要查询的表名  tag：要查询的标签 name：要查询的具体数据 member:帐号的结构体指针 time:存有时间的字符串
    查询失败将会返回-1,如果内容不存在将会返回0,存在则会返回查询语句返回的字段数目（大于0的值）
 */
int do_search(sqlite3 *db,char* listname,char* tag,char* name,memberlist member) {
    if(pointer_check(6,db,listname,tag,name,member,time) == -1 ){
        printf("pointer_chek err\n");
        return -1;
    }
    const char ch[128]="";
    sprintf((char *)ch,"select * from %s where %s='%s'",listname,tag,name);
    // printf("%s\n",ch);
    char *zErrMsg = NULL;
    int ret=-1,temp=0;
    ret=sqlite3_exec(db,ch,callback,&temp, &zErrMsg);//搜索

    if (ret != SQLITE_OK){
        temp =-1;   
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    if(temp > 0 && strcmp(listname,DICTIONALY_LISTNAME) == 0){//如果查询的数据存在，且目标为单词表
        sprintf((char *)ch,"%s_history",member->name);
        char time[64]="";
        now_time(time);//获取时间
        do_insert(db,(char *)ch,name,time);//将查询记录添加进历史记录
    }
    return temp;
}

/*  do_show 
    name:表名，函数作用：打印表中内容 
*/ 
int do_show(sqlite3 *db,char* name) {
    if(db == NULL){
        return -1;
    }
    char *zErrMsg = NULL;
    const char ch[128]="";
    int num=0;

    sprintf((char *)ch,"select * from %s",name);
    if (sqlite3_exec(db,ch, callback,NULL, &zErrMsg) != SQLITE_OK){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return -1;
    }
    return 0;
}


/*  member_insert
    将账户添加到帐号表中，如果账户存在，则会返回1,search模式下，将不会创建搜索历史表

*/
int member_insert(sqlite3 *db,memberlist member,int type){//将账户添加到帐号表中，如果账户存在，则会返回1,search模式下，将不会创建搜索历史表
    if(pointer_check(2,db,member,NULL,NULL,NULL,NULL) == -1 ){
        printf("pointer_chek err\n");
        return -1;
    }
    char *zErrMsg = NULL;

    if(do_search(db,MEMBER_LISTNAME,"name",member->name,member) > 0){
        // printf("存在\n");
        return 1;
    }else if(type != SEARCH){
        do_insert(db,MEMBER_LISTNAME,member->name,member->password);
        const char ch[128]="";
        sprintf((char *)ch,"create table %s_history(word text,time text)",member->name);
        if (sqlite3_exec(db,ch, callback,NULL, &zErrMsg) != SQLITE_OK){
            fprintf(stderr, "SQL error: %s\n", zErrMsg);
            sqlite3_free(zErrMsg);
        }
    }
    
    return 0;
}

int home_page(sqlite3 *db,memberlist member){
    char clean[64]="";
    char buf[32]="";
    int n=-1;
    while ( 1 ) {
        memset(buf,0,sizeof(buf));
        printf("**************************************************************\n"); 
        printf("1:查单词 2:查历史记录 3:退出\n"); 
        printf("**************************************************************\n"); 
        printf("please select : "); 
        if (scanf("%d", &n) != 1) { 
            fgets(clean, 64, stdin); 
            printf("\n"); 
            continue; 
        }
        switch ( n ) {
            case 1 : //单词查询
                printf("请输入查询的单词:\n");
                scanf("%s",buf);
                if(do_search(db,DICTIONALY_LISTNAME,"word",buf,member) == 0){
                    printf("不存在\n");
                }

                break; 
            case 2 ://历史记录查询
                sprintf(buf,"%s_history",member->name);
                printf("%s\n",buf);
                do_show(db,buf); 
                break; 
            case 3 : //退出
                sqlite3_close(db); 
                exit(0);
                break; 
            default: 
                printf("err option\n"); 
            break; 
        } 
    }
}

int login(sqlite3 *db,memberlist member){
    char clean[64]="";
    int n=-1;
    while ( 1 ) {
        printf("**************************************************************\n"); 
        printf("1: 登陆 2: 注册 3: 退出\n"); 
        printf("**************************************************************\n"); 
        printf("please select : "); 
        if (scanf("%d", &n) != 1) { 
            fgets(clean, 64, stdin); 
            printf("\n"); 
            continue; 
        }
        switch ( n ) {
            case 1 : //登陆
                printf("请输入帐号\n");
                scanf("%s",member->name);
                printf("请输入密码\n");
                scanf("%s",member->password);
                if(member_insert(db,member,SEARCH) == 1){//如果账户存在，则进入主页(type == SEARCH,为仅查询模式)
                    home_page(db,member);
                }
                break; 
            case 2 : //注册
                printf("请输入帐号\n");
                scanf("%s",member->name);
                printf("请输入密码\n");
                scanf("%s",member->password);
                if(member_insert(db,member,NO) == 1){//如果存在，则打印
                    printf("帐号已存在\n");
                }
                break; 
            case 3 : 
                sqlite3_close(db); 
                exit(0);
                break;  
            default: 
                printf("err option\n"); 
            break; 
        } 
    }
}

int main(void) { 
    sqlite3 *db; 
    int n=-1; 
    char clean[64]=""; 
    char *zErrMsg = NULL;
    if (sqlite3_open("my.db", &db) < 0) { 
        printf("fail to sqlite3_open : %s\n", sqlite3_errmsg(db)); 
        return -1; 
    }
    if (sqlite3_exec(db, "create table dictionary(word text,description text)", callback,NULL, &zErrMsg) != SQLITE_OK){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    if (sqlite3_exec(db, "create table member(name text,password text)", callback,NULL, &zErrMsg) != SQLITE_OK){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    
    membernode node;
    login(db,&node);
    return 0; 
}